#include "HackBoy.h"

using namespace HackBoyInterface;

int HackBoyInterface::FloatToInt(float fFloat)
{
	__try
	{
		float x = fFloat;
		void* px = &x;
		int* pd = (int*)px;

		return *pd;
	}
	__except(1)
	{
		return 0;
	}
}

bool HackBoy::IsPipeCreated()
{
	__try
	{
		if(!_pipe)
			return false;
		return true;
	}
	__except(1) { }
	return false;
}

bool HackBoy::Connect()
{
	bool bReturn = true;

	if(!IsPipeCreated())
	{
		HANDLE hProcessSnap;
		HANDLE hProcess;
		PROCESSENTRY32 pe32;

		char* pipeName = new char[30];

		hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if(hProcessSnap != INVALID_HANDLE_VALUE)
		{
			pe32.dwSize = sizeof(PROCESSENTRY32);

			Process32First(hProcessSnap, &pe32);
			do
			{
				if(_stricmp(pe32.szExeFile, "Game.exe") == 0)
				{
					if(sCharName)
					{
						hProcess = OpenProcess(PROCESS_VM_READ, false, pe32.th32ProcessID);
						if(hProcess != INVALID_HANDLE_VALUE)
						{
							char* pName = new char[20];
							ReadProcessMemory(hProcess, (void*)0xBD86D0, pName, 16, NULL);
							if(_stricmp(pName, sCharName) == 0)
							{
								delete pName;
								break;
							}
						}
						CloseHandle(hProcess); //close handle if not the right process
					}
					else
					{
						hProcess = OpenProcess(PROCESS_VM_READ, false, pe32.th32ProcessID);
						break;
					}
				}
			} while(Process32Next(hProcessSnap, &pe32));
		}
		else
		{
			bReturn = false;
		}
			
		if(hProcess > 0)
		{
			sprintf_s(pipeName, 30, "\\\\.\\pipe\\boy_%lu", pe32.th32ProcessID);
			_pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

			if(_pipe == INVALID_HANDLE_VALUE)
			{
				_pipe = NULL;
				bReturn = false;
			}
		}

		CloseHandle(hProcessSnap);
		CloseHandle(hProcess);
		delete pipeName;
	}
	return bReturn;
}

void HackBoy::Disconnect()
{
	CloseHandle(_pipe);
	_pipe = NULL;
}

bool HackBoy::SendMsg(MessageType msgType, PipeCommands uMsg, Param_t param1, Param_t param2, Param_t param3, Param_t param4, Param_t param5, char* buffer)
{
	WaitForSingleObject(_mutex, INFINITE);

	if(!IsPipeCreated())
	{
		Connect();
		if(!IsPipeCreated())
			return false;
	}

	__try
	{
		BaseMessage OutBuffer = BaseMessage();
		OutBuffer.header = (word)uMsg;
		OutBuffer.type = (word)msgType;
		OutBuffer.param1 = param1;
		OutBuffer.param2 = param2;
		OutBuffer.param3 = param3;
		OutBuffer.param4 = param4;
		OutBuffer.param5 = param5;
		
		if(buffer)
			strcpy_s(OutBuffer.buffer, 100, buffer);

		if(!WriteFile(_pipe, &OutBuffer, sizeof(BaseMessage), &_cbWritten, NULL))
		{
			Disconnect();
			ReleaseMutex(_mutex);
			return false;
		}

		if(msgType & IS_REQUEST)
		{
			if(!ReadFile(_pipe, InBuffer, sizeof(BaseMessage), &_cbRead, NULL))
			{
				Disconnect();
				ReleaseMutex(_mutex);
				return false;
			}
		}
	}
	__except(1)
	{
		ReleaseMutex(_mutex);
		return false;
	}

	ReleaseMutex(_mutex);
	return true;
}

void HackBoy::Cmd(PipeCommands uMsg, int param1, int param2, int param3, int param4, int param5, char* buffer)
{
	SendMsg((MessageType)(IS_NUMERIC | IS_COMMAND), uMsg,
		Param_t(param1), Param_t(param2), Param_t(param3), Param_t(param4), Param_t(param5),
		buffer);
}

void HackBoy::Cmd(PipeCommands uMsg, char* buffer, int param1, int param2, int param3, int param4, int param5)
{
	SendMsg((MessageType)(IS_NUMERIC | IS_COMMAND), uMsg,
		Param_t(param1), Param_t(param2), Param_t(param3), Param_t(param4), Param_t(param5),
		buffer);
}

BaseMessage* HackBoy::CmdCB(PipeCommands uMsg, int param1, int param2, int param3, int param4, int param5, char* buffer)
{
	SendMsg((MessageType)(IS_NUMERIC | IS_REQUEST), uMsg,
		Param_t(param1), Param_t(param2), Param_t(param3), Param_t(param4), Param_t(param5),
		buffer);
	return InBuffer;
}

BaseMessage* HackBoy::CmdCB(PipeCommands uMsg, char* buffer, int param1, int param2, int param3, int param4, int param5)
{
	SendMsg((MessageType)(IS_NUMERIC | IS_REQUEST), uMsg,
		Param_t(param1), Param_t(param2), Param_t(param3), Param_t(param4), Param_t(param5),
		buffer);
	return InBuffer;
}

void HackBoy::MoveTo(float X, float Y, int MapId)
{
	Cmd(CA_MoveTo, FloatToInt(X), FloatToInt(Y), MapId);
}

void HackBoy::SetDebugPrivilege()
{
	HANDLE hProcess = GetCurrentProcess(), hToken;
	TOKEN_PRIVILEGES priv;
	LUID luid;

	OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
	LookupPrivilegeValue(0, SE_DEBUG_NAME, &luid);
	priv.PrivilegeCount = 1;
	priv.Privileges[0].Luid = luid;
	priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	AdjustTokenPrivileges(hToken, false, &priv, 0, 0, 0);
	CloseHandle(hToken);
	CloseHandle(hProcess);
}